/**
 * 匹配 模型.
 */
const constants = require('../../utils/constants');
const models = require('../../utils/models');
const networkUtil = require('../../utils/network');
const fs = require("fs");
const rs = require('randomstring');

module.exports = class MatchModel extends think.Model {
    get tableName() {
        return 'user_match';
    }

    get relation() {
        return {
            photo: {
                type: think.Model.HAS_ONE,
                model: models.Photo,
                key: 'photoId',
                fKey: 'id'
            }
        }
    }

    /**
     * 获取一个待匹配记录，并处理。
     *
     * 根据mac过滤，每台服务器，仅能处理本机创建的请求。
     */
    async matchOne() {
        const mac = await networkUtil.getMacAddress();
        const match = await this.where({result: 0, mac: mac}).order('id asc').find();
        try {
            if (think.isEmpty(match) || think.isEmpty(match.photo.photoUrl)) return;

            const settingsModel = think.model(models.Settings);
            const settings = await settingsModel.getServerSideSettings();

            //
            const faceMgr = think.model(models.VendorBaiduFaceManager);

            let bid = match.photo.bid;
            let bUserInfo = match.photo.bUserInfo;
            let registerGroup = 'general';
            let photoPath = match.photo.photoPath;
            let actionType = 'append';
            let photoData = fs.readFileSync(photoPath).toString("base64");

            const bdAppModel = think.model(models.VendorBaiduApp);
            const bdApp = await bdAppModel.getOneByWxAppId(match.appid);

            // 匹配网友时，注册人脸(在普通用户组中注册)，需要根据微信appid获取关联的百度appid
            if (match.mode === constants.MatchMode.General) {
                faceMgr.register(bid, bUserInfo, registerGroup, photoData, actionType, bdApp);
            }

            // 匹配(仅匹配一个结果)
            let matchRes = await faceMgr.identifyUser(photoData, settings.modeGroups[match.mode], 1, bdApp);
            if (matchRes.error_code === 216618) {
                return this.where({id: match.id}).setRelation(false).update({
                    result: constants.MatchStatus.NoMatch,
                    notes: matchRes.error_msg
                });
            } else if (matchRes.error_msg || matchRes.error_code) {
                throw new Error(matchRes.error_msg);
            }

            matchRes = matchRes.result.length > 0 ? matchRes.result[0] : null;
            if (think.isEmpty(matchRes)) return;

            const matchScore  = matchRes.scores[0];
            if (matchRes.user_info.startsWith(match.userId)) {
                // 匹配到自己的头像，认为未匹配到具体的用户
                await this.where({id: match.id}).setRelation(false).update({
                    result: constants.MatchStatus.NoMatch,
                    bid: matchRes.uid,
                    bUserInfo: matchRes.user_info,
                    score: matchScore,
                    groupId: matchRes.group_id,
                    notes: '匹配到自己!'
                });
            } else {
                // 对比结果，小于匹配阀值，认为找不到匹配对象
                const matched = matchScore > settings.matchThreshold;

                // 记录匹配结果
                this.where({id: match.id}).setRelation(false).update({
                    result: matched ? constants.MatchStatus.Success : constants.MatchStatus.NoMatch,
                    bid: matchRes.uid,
                    bUserInfo: matchRes.user_info,
                    score: matchScore,
                    groupId: matchRes.group_id,
                    notes: JSON.stringify(matchRes)
                });

                // 结果通知用户(单方)，异步进行，不等待结果
                const tplMsgModel = think.model(models.VendorTencentTplMessage);
                const users = [{
                    matchId: match.id,
                    openid: match.openid,
                    formId: match.formId
                }];

                tplMsgModel.sendMatchResultMessage(match.appid, users);
            }

            // 删除本地文件
            fs.unlink(match.photo.photoPath, function (err) {
                if (err) think.logger.error(`删除头像照片失败: ${err.message}`);
            });
        } catch (err) {
            think.logger.error(`匹配计算出错: ${err.message}`);

            this.where({id: match.id}).setRelation(false).update({
                result: constants.MatchStatus.Error,
                notes: err.message
            });
        }
    }
};
